﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AddIn.EA.Architecture.Presentation.Common
{
    public class TabIndexEventArgs : EventArgs
    {
        public TabIndexEventArgs(Control control, int index)
        {
            this.Control = control;
            this.Index = index;
        }

        public Control Control {  get; private set; }
        public int Index { get; private set; }
    }

    public class ControlTabOrder : IList<Control>
    {
        private List<Control> _list = new List<Control>();

        public event EventHandler<TabIndexEventArgs> OnLastTabIndex;
        public event EventHandler<TabIndexEventArgs> OnFirstTabIndex;

        #region IList<Control> Members

        public int IndexOf(Control item)
        {
            return _list.IndexOf(item);
        }

        public void Insert(int index, Control item)
        {
            item.KeyDown += new KeyEventHandler(item_KeyDown);
            _list.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            this[index].KeyDown -= item_KeyDown;
            _list.RemoveAt(index);
        }

        public Control this[int index]
        {
            get
            {
                return _list[index];
            }
            set
            {
                _list[index] = value;
            }
        }

        #endregion

        #region ICollection<Control> Members

        public void Add(Control item)
        {
            item.KeyDown += new KeyEventHandler(item_KeyDown);
            _list.Add(item);
        }

        public void Clear()
        {
            foreach (Control control in this)
                control.KeyDown -= item_KeyDown;

            _list.Clear();
        }

        public bool Contains(Control item)
        {
            return _list.Contains(item);
        }

        public void CopyTo(Control[] array, int arrayIndex)
        {
            _list.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return _list.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(Control item)
        {
            item.KeyDown -= item_KeyDown;
            return _list.Remove(item);
        }

        #endregion

        #region IEnumerable<Control> Members

        public IEnumerator<Control> GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return (System.Collections.IEnumerator)_list.GetEnumerator();
        }

        #endregion


        public void MoveToFirst()
        {
            if (this.Count > 0)
            {
                foreach (Control control in this)
                {
                    if (control.Enabled)
                    {
                        this[0].Focus();
                        return;
                    }
                }

                if (OnLastTabIndex != null)
                    OnLastTabIndex(this, new TabIndexEventArgs(this[this.Count - 1], this.Count - 1));
            }
        }

        public void MoveToLast()
        {
            if (this.Count > 0)
            {
                for (int i = this.Count - 1; i >= 0; i++)
                {
                    if (this[i].Enabled)
                    {
                        this[i].Focus();
                        return;
                    }
                }

                if (OnFirstTabIndex != null)
                    OnFirstTabIndex(this, new TabIndexEventArgs(this[0], 0));
            }
        }

        private void item_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Tab && e.Shift && sender is Control)
            {
                int controlIndex = this.IndexOf((Control)sender);

                if (controlIndex == 0)
                {
                    if (OnFirstTabIndex != null)
                        OnFirstTabIndex(this, new TabIndexEventArgs(this[controlIndex], controlIndex));
                }
                else
                {
                    if (this[controlIndex - 1].Enabled)
                        this[controlIndex - 1].Focus();
                    else
                        item_KeyDown(this[controlIndex - 1], e);
                }
            }
            else if(e.KeyCode == Keys.Tab && sender is Control)
            {
                int controlIndex = this.IndexOf((Control)sender);

                if (controlIndex + 1 == this.Count)
                {
                    if (OnLastTabIndex != null)
                        OnLastTabIndex(this, new TabIndexEventArgs(this[controlIndex], controlIndex));
                }
                else
                {
                    if (this[controlIndex + 1].Enabled)
                        this[controlIndex + 1].Focus();
                    else
                        item_KeyDown(this[controlIndex + 1], e);
                }
            }
        }
    }
}
